home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FBALists.c
-
- Contains:
-
- Written by: Greg Sutton
-
- Copyright: Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 7/21/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
-
-
- */
-
-
- #include "FBALists.h"
-
- #include "FBA.h"
- #include "FBATask.h"
-
- #include <Memory.h>
- #include <Resources.h>
- #include <TextUtils.h>
- #include <ToolUtils.h>
-
- // Borrowed from MoreFiles 1.3.1
- #define hasCatSearch(volParms) (((volParms).vMAttrib & (1L << bHasCatSearch)) != 0)
-
- // Prototypes
- static void AddToList( ItemPtr* theHeadPtr, ItemPtr theItem );
- static void FirstToLast( ItemPtr* theHeadPtr );
- static WatchVolumePtr VolumeInList( short theVolRef );
- static OSErr GetFullPath( FSSpec* theSpec, StringPtr thePath );
- static void InsertAtBeginning( StringPtr sourceStr, StringPtr destStr );
- static OSErr GetVolInfo( short theVolRef, GetVolParmsInfoBuffer* theBuffer );
-
- // Globals
- long gNumberFolders = 0;
- long gNumberVolumes = 0;
- WatchFolderPtr gWatchFolderPtr = NULL;
- WatchVolumePtr gWatchVolumePtr = NULL;
-
- // Paths to the folder to be watched are stored in 'WFol' resources. This routine simply
- // reads through all of these resources adding them to the list of folders to watch.
-
- Boolean InitWatchFolders( void )
- {
- short count;
- Handle aHandle;
- FSSpec aSpec;
- OSErr err;
- Boolean result = true;
-
- count = Count1Resources( kWatchFolderResource );
-
- for ( ; count > 0; count-- )
- { // Handle to a pascal string
- aHandle = Get1IndResource( kWatchFolderResource, count );
-
- if (! aHandle)
- {
- result = false; // If we fail on one we'll still try the rest
- continue;
- }
-
- HLock( aHandle );
- err = FSMakeFSSpec( 0, 0, (StringPtr) *aHandle, &aSpec );
- HUnlock( aHandle );
-
- if (noErr != err || ! AddFolder( &aSpec ))
- {
- RemoveResource( aHandle ); // Error in finding the folder or
- result = false; // no longer a file - get rid of it.
- }
- else
- ReleaseResource( aHandle );
- }
-
- return result;
- }
-
-
- // Check that the FSSpec is for a folder. If it is then create a WatchFolderPtr
- // that gets added to the front of the linked list.
-
- Boolean AddFolder( FSSpec* theSpec )
- {
- WatchFolderPtr tempPtr;
- CInfoPBRec pb;
- OSErr err;
-
- if ( FolderInList( theSpec ) )
- return true;
-
- err = GetDirInfo( theSpec, &pb );
- // Check there's no error and FSSpec is a directory
- if ( noErr != err || ! ( pb.dirInfo.ioFlAttrib & ioDirMask ) )
- return false;
- // If folder is on a different
- if ( ! AddVolume( theSpec->vRefNum ) ) // volume to the others increment.
- return false; // Returns false if volume can't
- // handle PBCatSearch().
-
- tempPtr = (WatchFolderPtr) NewPtr( sizeof( WatchFolderRec ) );
- tempPtr->theSpec = *theSpec;
- tempPtr->theDirID = pb.dirInfo.ioDrDirID;
- tempPtr->theFileCount = pb.dirInfo.ioDrNmFls;
- tempPtr->next = NULL;
-
- AddToList( (ItemPtr *)&gWatchFolderPtr, (ItemPtr)tempPtr );
-
- gNumberFolders++;
-
- return true;
- }
-
-
- // Check that the volume supports PBCatSearch(), if so create a
- // WatchVolumePtr and add to volume linked list.
-
-
- Boolean AddVolume( short theVolRef )
- {
- WatchVolumePtr tempPtr;
- GetVolParmsInfoBuffer aBuffer;
- OSErr err;
-
- if ( VolumeInList( theVolRef ) )
- return true;
-
- err = GetVolInfo( theVolRef, &aBuffer );
- // Check there's no error and FSSpec is a directory
- if ( noErr != err || ! hasCatSearch( aBuffer ) )
- return false;
-
- tempPtr = (WatchVolumePtr) NewPtr( sizeof( WatchVolumeRec ) );
- tempPtr->theVolRef = theVolRef;
- GetDateTime( &tempPtr->theLastModCheck );
- tempPtr->next = NULL;
-
- AddToList( (ItemPtr *)&gWatchVolumePtr, (ItemPtr)tempPtr );
-
- gNumberVolumes++;
-
- return true;
- }
-
-
- // Just set up a parameter block for a PBHGetVolParms() call.
-
- static OSErr GetVolInfo( short theVolRef, GetVolParmsInfoBuffer* theBuffer )
- {
- HParamBlockRec pb;
- OSErr err;
-
- pb.ioParam.ioCompletion = NULL;
- pb.ioParam.ioNamePtr = NULL;
- pb.ioParam.ioVRefNum = theVolRef;
- pb.ioParam.ioBuffer = (Ptr)theBuffer;
- pb.ioParam.ioReqCount = sizeof( *theBuffer );
-
- err = PBHGetVolParms( &pb, false ); // Won't do this asynchronusly
-
- return err;
- }
-
-
- // Get directory information for an FSSpec.
-
- OSErr GetDirInfo( FSSpec* theSpec, CInfoPBRec* thePB)
- {
- OSErr err;
-
- thePB->dirInfo.ioNamePtr = theSpec->name;
- thePB->dirInfo.ioVRefNum = theSpec->vRefNum;
- thePB->dirInfo.ioDrDirID = theSpec->parID;
- thePB->dirInfo.ioFDirIndex = 0; // Use ioNamePtr and ioDirID
- thePB->dirInfo.ioACUser = 0; // If this does not compile try using
- // thePB->dirInfo.filler2 or thePB->dirInfo.ioACUser
- // Clear it before calling PBGetCatInfo()
- err = PBGetCatInfo( thePB, false );
-
- return err;
- }
-
-
- // Just add the item to the beginning of the linked list
-
- static void AddToList( ItemPtr* theHeadPtr, ItemPtr theItem )
- {
- ItemPtr tempPtr = *theHeadPtr;
-
- *theHeadPtr = theItem;
- theItem->next = tempPtr;
- }
-
- // Just keep gWatchFolderPtr referred to in this file.
-
- WatchFolderPtr GetHeadFolderPtr( void )
- {
- return gWatchFolderPtr;
- }
-
- WatchVolumePtr GetHeadVolumePtr( void )
- {
- return gWatchVolumePtr;
- }
-
- long GetNumberOfVolumes( void )
- {
- return gNumberVolumes;
- }
-
- long GetNumberOfFolders( void )
- {
- return gNumberFolders;
- }
-
- void FirstVolumeToLast( void )
- {
- FirstToLast( (ItemPtr *)&gWatchVolumePtr );
- }
-
-
- // Move the first item in the watch folder list to the end of the list.
- // Handles an empty or one item list.
-
- static void FirstToLast( ItemPtr* theHeadPtr )
- {
- ItemPtr tempPtr = *theHeadPtr;
-
- // If no items in list
- if ( ! tempPtr )
- return;
-
- while ( tempPtr->next ) // Go to the last item in the linked list
- tempPtr = tempPtr->next;
-
- if ( tempPtr != *theHeadPtr ) // Would be equal if only one folder to watch
- { // - then the first is the last already.
- tempPtr->next = *theHeadPtr; // Add old head of list to end
- tempPtr = *theHeadPtr; // Keep so can NULL next
- *theHeadPtr = (*theHeadPtr)->next; // Head of list is now next in list
- tempPtr->next = NULL; // Now at end of list, so next is NULL
- }
- }
-
-
- // Given an FSSpec, get the full path to the folder specified and add it to our
- // 'WFol' resources. It will then be loaded by InitWatchFolders() when launched.
-
- void AddFolderPathResource( FSSpec* theSpec )
- {
- Str255 aPath;
- Handle aHandle;
-
- if ( noErr != GetFullPath( theSpec, aPath ) )
- return;
-
- aHandle = (Handle)NewHandle( aPath[0] + 1 );
- HLock( aHandle );
- BlockMoveData( aPath, *aHandle, aPath[0] + 1 );
- HUnlock( aHandle );
-
- AddResource( aHandle, kWatchFolderResource, Unique1ID( kWatchFolderResource ), theSpec->name );
- ReleaseResource( aHandle );
- }
-
-
- // Check through linked list to see if a folder with this volume is already
- // there.
-
- static WatchVolumePtr VolumeInList( short theVolRef )
- {
- WatchVolumePtr tempPtr = GetHeadVolumePtr( );
-
- while ( tempPtr )
- {
- if ( theVolRef == tempPtr->theVolRef )
- break;
-
- tempPtr = (WatchVolumePtr)tempPtr->next;
- }
-
- return tempPtr;
- }
-
-
- // Check through linked list to see if this file spec is already there.
-
- WatchFolderPtr FolderInList( FSSpec* theSpec )
- {
- WatchFolderPtr tempPtr = GetHeadFolderPtr( );
-
- if ( ! theSpec )
- return NULL;
-
- while ( tempPtr )
- {
- if ( theSpec->vRefNum == tempPtr->theSpec.vRefNum
- && theSpec->parID == tempPtr->theSpec.parID
- && EqualString( theSpec->name, tempPtr->theSpec.name, false, false ) )
- {
- break;
- }
-
- tempPtr = (WatchFolderPtr)tempPtr->next;
- }
-
- return tempPtr;
- }
-
-
- // Check through linked list to see if this volume and the directory
- // id are of a folder being watched.
-
- Boolean VolumeAndDirIDInList( short theVolRef, long theDirID )
- {
- WatchFolderPtr tempPtr = GetHeadFolderPtr( );
- Boolean result = false;
-
- while ( tempPtr )
- {
- if ( theVolRef == tempPtr->theSpec.vRefNum
- && theDirID == tempPtr->theDirID )
- {
- result = true;
- break;
- }
-
- tempPtr = (WatchFolderPtr)tempPtr->next;
- }
-
- return result;
- }
-
-
- // Given an FSFSpec return the full path name for it.
-
- static OSErr GetFullPath( FSSpec* theSpec, StringPtr thePath )
- {
- CInfoPBRec pb;
- Str255 dirName;
- OSErr err;
-
- thePath[0] = 0; // Null the string
- InsertAtBeginning( theSpec->name, thePath );
- InsertAtBeginning( "\p:", thePath ); // Add the folder name
-
- pb.dirInfo.ioNamePtr = dirName;
- pb.dirInfo.ioVRefNum = theSpec->vRefNum;
- pb.dirInfo.ioDrParID = theSpec->parID;
- pb.dirInfo.ioFDirIndex = -1; // Get info about the directory
-
- do
- {
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- err = PBGetCatInfo( &pb, false);
- if ( noErr != err ) goto done;
-
- InsertAtBeginning( dirName, thePath );
- if ( pb.dirInfo.ioDrDirID != fsRtDirID ) // If it's not the disk name
- InsertAtBeginning( "\p:", thePath ); // Then add a : ready for next directory
-
- } while ( pb.dirInfo.ioDrDirID != fsRtDirID );
-
- done:
- return err;
- }
-
-
- // Simply inserts the pascal source string at the beginning of the
- // destination pascal string.
-
- static void InsertAtBeginning( StringPtr sourceStr, StringPtr destStr )
- {
- BlockMoveData( (void *)&destStr[1], (void *)( &destStr[1] + sourceStr[0] ), destStr[0] );
- BlockMoveData( (void *)&sourceStr[1], (void *)&destStr[1], sourceStr[0] );
- destStr[0] += sourceStr[0];
- }
-